package com.zzedu.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zzedu.common.annotation.DataScope;
import com.zzedu.common.core.domain.entity.SysUser;
import com.zzedu.common.enums.CommonEnums;
import com.zzedu.common.enums.DeletedEnums;
import com.zzedu.common.enums.UserTypeEnumns;
import com.zzedu.common.utils.DateUtils;
import com.zzedu.common.utils.SecurityUtils;
import com.zzedu.common.utils.StringUtils;
import com.zzedu.common.utils.bean.BeanUtils;
import com.zzedu.common.utils.spring.SpringUtils;
import com.zzedu.domain.*;
import com.zzedu.dto.ZzStudentDTO;
import com.zzedu.enmuns.ConfigEnums;
import com.zzedu.enmuns.FileRelationTypeEnum;
import com.zzedu.enmuns.StuTypeEnum;
import com.zzedu.framework.config.RedisIdWorker;
import com.zzedu.framework.lock.IDistributedLockService;
import com.zzedu.framework.transaction.ITransactionHandlerService;
import com.zzedu.framework.web.service.SysPasswordService;
import com.zzedu.integration.oss.IOssClientService;
import com.zzedu.mapper.ZzClassesMapper;
import com.zzedu.mapper.ZzStudentMapper;
import com.zzedu.service.*;
import com.zzedu.system.service.ISysConfigService;
import com.zzedu.system.service.ISysRegionService;
import com.zzedu.vo.ZzStudentVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 学生信息Service业务层处理
 *
 * @author Mr.Wang
 * @date 2025-02-16
 */
@Service
public class ZzStudentServiceImpl extends ServiceImpl<ZzStudentMapper, ZzStudent> implements IZzStudentService {
    @Autowired
    IZzSchoolService zzSchoolService;

    @Autowired
    ISysRegionService sysRegionService;

    @Autowired
    IZzUploadFileService zzUploadFileService;

    @Autowired
    IOssClientService ossClientService;

    @Autowired
    RedisIdWorker redisIdWorker;


    @Autowired
    SysPasswordService passwordService;

    @Autowired
    ISysConfigService sysConfigService;

    @Autowired
    IDistributedLockService distributedLockService;

    @Autowired
    ITransactionHandlerService transactionHandlerService;


    @Autowired
    IZzStuLogService zzStuLogService;

    @Autowired
    ZzClassesMapper zzClassesMapper;

    @Autowired
    IZzTeacherService zzTeacherService;

    @Autowired
    IZzStuRenewOrderService zzStuRenewOrderService;

    @Autowired
    IZzExerciseBookService zzExerciseBookService;

    @Autowired
    IZzPictureBookService zzPictureBookService;

    @Autowired
    IZzCourseService zzCourseService;

    @Autowired
    IZzStudentExtendService zzStudentExtendService;

    @Override
    public LambdaQueryWrapper<ZzStudent> buildQuery(ZzStudentDTO zzStudent) {
        LambdaQueryWrapper<ZzStudent> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.like(StringUtils.isNotBlank(zzStudent.getStuName()), ZzStudent::getStuName, zzStudent.getStuName());
        lambdaQueryWrapper.like(StringUtils.isNotBlank(zzStudent.getNickName()), ZzStudent::getNickName, zzStudent.getNickName());
        lambdaQueryWrapper.eq(null != zzStudent.getStuType(), ZzStudent::getStuType, zzStudent.getStuType());
        lambdaQueryWrapper.eq(null != zzStudent.getMemberType(), ZzStudent::getMemberType, zzStudent.getMemberType());
        lambdaQueryWrapper.eq(null != zzStudent.getStuSex(), ZzStudent::getStuSex, zzStudent.getStuSex());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzStudent.getStuCode()), ZzStudent::getStuCode, zzStudent.getStuCode());
        lambdaQueryWrapper.like(StringUtils.isNotBlank(zzStudent.getTel()), ZzStudent::getTel, zzStudent.getTel());
        lambdaQueryWrapper.eq(null != zzStudent.getBirthDay(), ZzStudent::getBirthDay, zzStudent.getBirthDay());
        lambdaQueryWrapper.eq(null != zzStudent.getSchoolId(), ZzStudent::getSchoolId, zzStudent.getSchoolId());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzStudent.getProvince()), ZzStudent::getProvince, zzStudent.getProvince());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzStudent.getCity()), ZzStudent::getCity, zzStudent.getCity());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzStudent.getDistrict()), ZzStudent::getDistrict, zzStudent.getDistrict());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(zzStudent.getAddress()), ZzStudent::getAddress, zzStudent.getAddress());
        lambdaQueryWrapper.eq(null != zzStudent.getState(), ZzStudent::getState, zzStudent.getState());
        if (CollectionUtils.isNotEmpty(zzStudent.getSchoolIdArray())) {
            lambdaQueryWrapper.in(ZzStudent::getSchoolId, zzStudent.getSchoolIdArray());
        }
        if (null != zzStudent.getOrgId()) {
            lambdaQueryWrapper.apply("school_id in (select id from zz_school where deleted=0 and org_id={0})", zzStudent.getOrgId());

        }
        if (null != zzStudent.getClzzFlag()) {
            CommonEnums commonEnums = CommonEnums.getCode(zzStudent.getClzzFlag());
            if (CommonEnums.YES == commonEnums) {
                lambdaQueryWrapper.apply("id in(select stu_id from zz_stu_classes_r where class_id in(select id from zz_classes where deleted={0}) and deleted={1})", DeletedEnums.NO.getCode(), DeletedEnums.NO.getCode());
            } else if (CommonEnums.NO == commonEnums) {
                lambdaQueryWrapper.apply("id not in(select stu_id from zz_stu_classes_r where class_id in(select id from zz_classes where deleted={0}) and deleted={1})", DeletedEnums.NO.getCode(), DeletedEnums.NO.getCode());
            }
        }
        List<String[]> queryProvinceAndCityAndDistrict = zzStudent.getQueryProvinceAndCityAndDistrict();
        if (CollectionUtils.isNotEmpty(queryProvinceAndCityAndDistrict)) {
            List<String> province = Lists.newArrayList();
            List<String> city = Lists.newArrayList();
            List<String> district = Lists.newArrayList();
            for (String[] provinceAndCityAndDistrict : queryProvinceAndCityAndDistrict) {
                if (null == provinceAndCityAndDistrict) {
                    continue;
                }
                if (StringUtils.isNotBlank(provinceAndCityAndDistrict[0])) {
                    province.add(provinceAndCityAndDistrict[0]);
                }
                if (provinceAndCityAndDistrict.length > 1 && StringUtils.isNotBlank(provinceAndCityAndDistrict[1])) {
                    city.add(provinceAndCityAndDistrict[1]);
                }
                if (provinceAndCityAndDistrict.length > 2 && StringUtils.isNotBlank(provinceAndCityAndDistrict[2])) {
                    district.add(provinceAndCityAndDistrict[2]);
                }
            }
            lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(province), ZzStudent::getProvince, province);
            lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(city), ZzStudent::getCity, city);
            lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(district), ZzStudent::getDistrict, district);
        }

        if (null != zzStudent.getIncludeClassId()) {
            lambdaQueryWrapper.exists("select stu_id from zz_stu_classes_r where stu_id=zz_student.id and deleted=0 and class_id={0}", zzStudent.getIncludeClassId());
        }
        if (null != zzStudent.getExcludeClassId()) {
            lambdaQueryWrapper.notExists("select stu_id from zz_stu_classes_r where stu_id=zz_student.id and deleted=0 and class_id={0}", zzStudent.getExcludeClassId());
        }
        lambdaQueryWrapper.orderByDesc(ZzStudent::getId);
        return lambdaQueryWrapper;
    }

    @DataScope(otherIdColumnName = "school_id")
    public <E extends IPage<ZzStudent>> E page(E page, Wrapper<ZzStudent> queryWrapper) {
        return super.page(page, queryWrapper);
    }


    @Override
    public List<ZzStudentVO> convertVO(List<ZzStudent> zzStudentList) {
        final Map<Long, String> stuTimeMap = Maps.newConcurrentMap();
        final Map<Long, Long> stuBookMap = Maps.newConcurrentMap();
        final Map<Long, String> bookIdAndName = Maps.newConcurrentMap();
        final Map<Long, String> stuIdAndBookName = Maps.newConcurrentMap();
        final Map<Long, String> stuIdAndTearchName = Maps.newConcurrentMap();
        final Map<Long, String> stuIdAndClzzName = Maps.newConcurrentMap();
        if (CollectionUtils.isNotEmpty(zzStudentList)) {
            List<Long> studentIdList = zzStudentList.stream().map(ZzStudent::getId).collect(Collectors.toList());
            List<Map<String, Object>> mapList = zzExerciseBookService.studentStudyInfoByStudentIdList(studentIdList);
            if (CollectionUtils.isNotEmpty(mapList)) {
                for (Map<String, Object> map : mapList) {
                    String info = DateUtils.formatSeconds(MapUtils.getLong(map, "sumTimes", 0L));
                    stuTimeMap.put(MapUtils.getLong(map, "stuId"), info);
                    stuBookMap.put(MapUtils.getLong(map, "stuId"), MapUtils.getLong(map, "lastBookId", 0L));
                }
                List<ZzPictureBook> zzPictureBookList = zzPictureBookService.listByIds(stuBookMap.values());
                Map<Long, String> unitNameMap = Maps.newHashMap();
                if (CollectionUtils.isNotEmpty(zzPictureBookList)) {
                    for (ZzPictureBook zzPictureBook : zzPictureBookList) {
                        if (!unitNameMap.containsKey(zzPictureBook.getUnitId())) {
                            ZzCourse zzCourse = zzCourseService.getById(zzPictureBook.getUnitId());
                            if (null != zzCourse) {
                                unitNameMap.put(zzPictureBook.getUnitId(), zzCourse.getName());
                            }
                        }
                        String unitName = MapUtils.getString(unitNameMap, zzPictureBook.getUnitId(), "");
                        bookIdAndName.put(zzPictureBook.getId(), (StringUtils.isNotBlank(unitName) ? unitName + "-" : "") + zzPictureBook.getName());
                    }
                }
                for (Map<String, Object> map : mapList) {
                    Long stuId = MapUtils.getLong(map, "stuId");
                    Long bookId = MapUtils.getLong(map, "lastBookId", 0L);
                    String bookName = MapUtils.getString(bookIdAndName, bookId, "");
                    stuIdAndBookName.put(stuId, bookName);
                }
            }
            List<Map<String, Object>> clzzInfoMapList = zzClassesMapper.selectStudentClzzInfo(studentIdList);
            if (CollectionUtils.isNotEmpty(clzzInfoMapList)) {
                for (Map<String, Object> map : clzzInfoMapList) {
                    stuIdAndTearchName.put(MapUtils.getLong(map, "stuId"), MapUtils.getString(map, "teacherName", ""));
                    stuIdAndClzzName.put(MapUtils.getLong(map, "stuId"), MapUtils.getString(map, "clzzName", ""));
                }
            }

        }
        final Map<Long, String> stuIdSchoolName = Maps.newConcurrentMap();
        return Optional.ofNullable(zzStudentList).orElse(Lists.newArrayList()).stream().map(zzStudent -> {
            ZzStudentVO zzStudentVO = new ZzStudentVO();
            BeanUtils.copyBeanProp(zzStudentVO, zzStudent);
            if (!stuIdSchoolName.containsKey(zzStudent.getSchoolId())) {
                ZzSchool zzSchool = this.zzSchoolService.getById(zzStudent.getSchoolId());
                stuIdSchoolName.put(zzStudent.getSchoolId(), "");
                if (null != zzSchool) {
                    stuIdSchoolName.put(zzStudent.getSchoolId(), zzSchool.getSchoolName());
                }
            }
            zzStudentVO.setSchoolName(MapUtils.getString(stuIdSchoolName, zzStudent.getSchoolId(), ""));
            zzStudentVO.setStudyInfo(MapUtils.getString(stuTimeMap, zzStudent.getId(), ""));

            zzStudentVO.setBookInfo(MapUtils.getString(stuIdAndBookName, zzStudent.getId(), ""));
            if (null != zzStudent.getAvatar()) {
                ZzUploadFile zzUploadFile = this.zzUploadFileService.getById(zzStudent.getAvatar());
                if (null != zzUploadFile) {
                    zzStudentVO.setAvatarURL(ossClientService.convertURL(zzUploadFile.getUrl()));
                }
            }
            List<String> provinceAndCityAndDistrict = sysRegionService.provinceAndCityAndDistrict(Lists.newArrayList(zzStudent.getProvince(), zzStudent.getCity(), zzStudent.getDistrict()));
            if (CollectionUtils.isNotEmpty(provinceAndCityAndDistrict)) {
                zzStudentVO.setProvinceAndCityAndDistrict(Joiner.on("/").join(provinceAndCityAndDistrict));
            }
            zzStudentVO.setClzzNames(MapUtils.getString(stuIdAndClzzName, zzStudent.getId(), ""));
            zzStudentVO.setTeacherNames(MapUtils.getString(stuIdAndTearchName, zzStudent.getId(), ""));
            String[] validToDate = new String[4];
            LocalDateTime now = zzStudent.getValidTo();
            if (LocalDateTime.now().isAfter(now)) {
                //已经过期
                now = LocalDateTime.now();
            }
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            Map<Integer, Long> daysMap = Maps.newHashMap();
            daysMap.put(1, 92L);
            daysMap.put(2, 183L);
            daysMap.put(3, 275L);
            daysMap.put(4, 366L);
            for (int i = 1; i <= 4; i++) {
                validToDate[(i - 1)] = now.plusDays(daysMap.get(i)).format(dateTimeFormatter);
            }
            zzStudentVO.setValidToDate(validToDate);
            return zzStudentVO;
        }).collect(Collectors.toList());
    }

    @DataScope(otherIdColumnName = "school_id")
    public ZzStudent getOwnerById(Serializable id) {
        return super.getById(id);
    }

    @Override
    public boolean save(ZzStudentDTO zzStudentDTO) {
        String lockName = "stu:crud";
        if (null != zzStudentDTO.getId()) {
            ZzStudent zzStudent = SpringUtils.getAopProxy(this).getOwnerById(zzStudentDTO.getId());
            Assert.notNull(zzStudent, "学生信息不存在");
        }
        return distributedLockService.executeWithLock(lockName, 60L, 60L, TimeUnit.SECONDS, () -> transactionHandlerService.runInTransaction(() -> {
            ZzStudent zzStudent = new ZzStudent();
            BeanUtils.copyBeanProp(zzStudent, zzStudentDTO);
            zzStudent.setStuCode("S" + redisIdWorker.generateNextId(RedisIdWorker.STU_KEY_PREFIX));
            String[] provinceAndCityAndDistrict = zzStudentDTO.getProvinceAndCityAndDistrict();
            if (null != provinceAndCityAndDistrict) {
                zzStudent.setProvince(provinceAndCityAndDistrict[0]);
                if (provinceAndCityAndDistrict.length > 1) {
                    zzStudent.setCity(provinceAndCityAndDistrict[1]);
                }
                if (provinceAndCityAndDistrict.length > 2) {
                    zzStudent.setDistrict(provinceAndCityAndDistrict[2]);
                }
            }
            if (null != zzStudent.getAvatar()) {
                //移除之前关联的附件
                zzUploadFileService.remove(Wrappers.lambdaQuery(ZzUploadFile.class).eq(ZzUploadFile::getRelationId, String.valueOf(zzStudent.getId())).eq(ZzUploadFile::getRelationType, FileRelationTypeEnum.STU_AVATAR.getCode()).notIn(ZzUploadFile::getId, Lists.newArrayList(zzStudent.getAvatar())));
                zzUploadFileService.updateRelation(String.valueOf(zzStudent.getId()), Lists.newArrayList(zzStudent.getAvatar()));
            }
            SysUser sysUser = SecurityUtils.getSysUser();
            UserTypeEnumns userType = UserTypeEnumns.getCode(sysUser.getUserType());
            if (UserTypeEnumns.SCHOOL == userType) {
                zzStudent.setSchoolId(sysUser.getUserTypeId());
            }
            ZzSchool zzSchool = this.zzSchoolService.getById(zzStudent.getSchoolId());
            Assert.notNull(zzSchool, "所属学校不能为空");
            if (zzStudent.getId() == null) {
                //保存时候验证人数
                Integer studentCapacity = zzSchool.getStudentCapacity();
                long sumStudentCapacity = count(Wrappers.lambdaQuery(ZzStudent.class)
                        .eq(ZzStudent::getStuType, StuTypeEnum.FORMAL.getCode())
                        .eq(ZzStudent::getSchoolId, zzSchool.getId()));
                Assert.isTrue(sumStudentCapacity + 1 <= studentCapacity.longValue(), "超过该校允许招生人数");
            }
            StuTypeEnum stuTypeEnum = StuTypeEnum.getCode(zzStudent.getStuType());
            if (stuTypeEnum == null) {
                stuTypeEnum = StuTypeEnum.FORMAL;
            }
            if (zzStudent.getId() == null && StuTypeEnum.FORMAL == stuTypeEnum) {
                //
                LocalDateTime now = zzStudent.getValidFrom();
                LocalDateTime end = null;
                int numberOfClassHours = 0;
                if (1 == zzStudent.getMemberType()) {
                    end = now.plusDays(92);
                    numberOfClassHours = 26;
                } else if (2 == zzStudent.getMemberType()) {
                    end = now.plusDays(183);
                    numberOfClassHours = 50;
                } else if (3 == zzStudent.getMemberType()) {
                    end = now.plusDays(275);
                    numberOfClassHours = 76;
                } else if (4 == zzStudent.getMemberType()) {
                    end = now.plusDays(366);
                    numberOfClassHours = 100;
                }
                end = LocalDateTime.of(end.toLocalDate(), LocalTime.of(23, 59, 59));
                zzStudent.setValidFrom(now);
                zzStudent.setValidTo(end);
                if (!StringUtils.isNotBlank(zzStudent.getPwd())) {
                    zzStudent.setPwd(sysConfigService.selectConfigByKey(ConfigEnums.SYS_USER_INITPASSWORD.getCode()));
                }
                zzStudent.setPwd(passwordService.encryptPassword(zzStudent.getPwd()));
                boolean res = save(zzStudent);
                ZzStuLog zzStuLog = new ZzStuLog();
                zzStuLog.setAction(2);
                zzStuLog.setStuId(zzStudent.getId());
                zzStuLog.setExpireAt(end);
                zzStuLog.setOper(zzStudent.getMemberType().longValue());
                zzStuLogService.save(zzStuLog);
                zzStuRenewOrderService.addOrder(zzStudent.getId(), zzStudent.getMemberType(), 1, zzStudent, zzSchool, end, now, true);
                ZzStudentExtend zzStudentExtend = new ZzStudentExtend();
                zzStudentExtend.setId(zzStudent.getId());
                zzStudentExtend.setNumberOfClassHours(numberOfClassHours);
                zzStudentExtendService.save(zzStudentExtend);
                return res;
            } else {
                if (StringUtils.isNotBlank(zzStudent.getPwd())) {
                    zzStudent.setPwd(passwordService.encryptPassword(zzStudent.getPwd()));
                }
                return updateById(zzStudent);
            }
        }));
    }

    @Override
    @Transactional(rollbackFor = Exception.class, readOnly = false)
    public boolean renew(Long id, Integer memberType, String startDate) {
        ZzStudent zzStudent = SpringUtils.getAopProxy(this).getOwnerById(id);
        StuTypeEnum stuTypeEnum = StuTypeEnum.getCode(zzStudent.getStuType());
        ZzSchool zzSchool = this.zzSchoolService.getById(zzStudent.getSchoolId());
        Assert.notNull(zzStudent, "学生信息不存在");
        Assert.notNull(zzSchool, "学生学校信息不存在");
        Assert.isTrue(stuTypeEnum == StuTypeEnum.FORMAL, "体验学员不允许续费");
        zzStudent.setMemberType(memberType);
        LocalDateTime now = zzStudent.getValidTo();
        if (StringUtils.isNotBlank(startDate)) {
            LocalDateTime startTime = LocalDateTime.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            Assert.isTrue(startTime.toLocalDate().isAfter(now.toLocalDate()), "开始时间不能小于上一条订单的结束日期:" + zzStudent.getValidTo().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            now = startTime;
        }
        boolean isExpire = false;
        if (LocalDateTime.now().isAfter(now)) {
            //已经过期
            now = LocalDateTime.now();
            isExpire = true;
        }
        LocalDateTime end = null;
        int numberOfClassHours = 0;
        if (1 == zzStudent.getMemberType()) {
            end = now.plusDays(92);
            numberOfClassHours = 26;
        } else if (2 == zzStudent.getMemberType()) {
            end = now.plusDays(183);
            numberOfClassHours = 50;
        } else if (3 == zzStudent.getMemberType()) {
            end = now.plusDays(275);
            numberOfClassHours = 76;
        } else if (4 == zzStudent.getMemberType()) {
            end = now.plusDays(366);
            numberOfClassHours = 100;
        }
        if (null == zzStudent.getValidFrom()) {
            zzStudent.setValidFrom(now);
        }
        //直接当天结束
        end = LocalDateTime.of(end.toLocalDate(), LocalTime.of(23, 59, 59));
        zzStudent.setValidTo(end);
        ZzStuLog zzStuLog = new ZzStuLog();
        zzStuLog.setAction(2);
        zzStuLog.setStuId(id);
        zzStuLog.setExpireAt(end);
        zzStuLog.setOper(zzStudent.getMemberType().longValue());
        zzStuLogService.save(zzStuLog);
        zzStuRenewOrderService.addOrder(id, memberType, 2, zzStudent, zzSchool, end, now, isExpire);
        if (isExpire) {
            LambdaUpdateWrapper<ZzStudentExtend> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(ZzStudentExtend::getId, zzStudent.getId());
            updateWrapper.set(ZzStudentExtend::getNumberOfClassHours, numberOfClassHours);
            zzStudentExtendService.update(updateWrapper);
        } else {
            LambdaUpdateWrapper<ZzStudentExtend> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(ZzStudentExtend::getId, zzStudent.getId());
            updateWrapper.setIncrBy(ZzStudentExtend::getNumberOfClassHours, numberOfClassHours);
            zzStudentExtendService.update(updateWrapper);
        }
        return this.updateById(zzStudent);
    }

    @Override
    public ZzStudentVO convertVO(ZzStudent zzStudent) {
        ZzStudentVO zzStudentVO = new ZzStudentVO();
        if (null != zzStudent) {
            zzStudentVO = convertVO(Lists.newArrayList(zzStudent)).get(0);
        }
        return zzStudentVO;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean removeBatchByIds(List<Long> list) {
        //删除学生
        List<ZzStudent> zzStudentList = this.listByIds(list);
        if (CollectionUtils.isNotEmpty(zzStudentList)) {
            for (ZzStudent zzStudent : zzStudentList) {
                Assert.isTrue(null == zzExerciseBookService.getOne(Wrappers.lambdaQuery(ZzExerciseBook.class)
                        .eq(ZzExerciseBook::getStudentId, zzStudent.getId())
                        .last("limit 1")
                ), "存在使用记录,不允许删除");
                //有付款订单
                Assert.isTrue(null == zzStuRenewOrderService.getOne(Wrappers.lambdaQuery(ZzStuRenewOrder.class)
                        .eq(ZzStuRenewOrder::getStuId, zzStudent.getId())
                        .eq(ZzStuRenewOrder::getPayState, CommonEnums.YES.getCode())
                        .last("limit 1")
                ), "存在付款订单,不允许删除");
                zzStudent.setStuType(StuTypeEnum.ABANDONMENT.getCode());
                this.updateById(zzStudent);
                this.removeById(zzStudent.getId());
                zzStudentExtendService.removeById(zzStudent.getId());
                zzStuRenewOrderService.remove(Wrappers.lambdaQuery(ZzStuRenewOrder.class)
                        .eq(ZzStuRenewOrder::getStuId, zzStudent.getId()));
            }
        }
        return true;
    }

    /**
     * 初始化订单数据
     */
//    @PostConstruct
//    @Transactional
    public void initOrderData() {
        List<ZzStudent> zzStudentList = this.list(Wrappers.lambdaQuery(ZzStudent.class).apply("id not in(select stu_id from zz_stu_renew_order)"));
        for (ZzStudent zzStudent : zzStudentList) {
            LocalDateTime end = zzStudent.getValidTo();
            // 计算个月数量
            long months = ChronoUnit.MONTHS.between(zzStudent.getValidFrom(), end);
           /* if (months == 3) {
                zzStudent.setMemberType(1);
            } else if (months == 6) {
                zzStudent.setMemberType(2);
            } else if (months == 9) {
                zzStudent.setMemberType(3);
            } else if (months == 12) {
                zzStudent.setMemberType(4);
            }
            end = LocalDateTime.of(end.toLocalDate(), LocalTime.of(23, 59, 59));
            zzStudent.setValidTo(end);
            this.updateById(zzStudent);*/

            ZzSchool zzSchool = this.zzSchoolService.getById(zzStudent.getSchoolId());
            if (zzSchool == null) {
                continue;
            }
            ZzStuRenewOrder zzStuRenewOrder = new ZzStuRenewOrder();
            zzStuRenewOrder.setRenewType(zzStudent.getMemberType());
            zzStuRenewOrder.setSchoolId(zzSchool.getId());
            zzStuRenewOrder.setFeeType(zzSchool.getFeeType());
            zzStuRenewOrder.setOrderType(1);
            zzStuRenewOrder.setExpireDate(zzStudent.getValidTo());
            zzStuRenewOrder.setStartDate(zzStudent.getValidTo());
            zzStuRenewOrder.setStuId(zzStudent.getId());
            BigDecimal referencePrice = zzSchool.getReferencePrice();
            Integer feeType = zzSchool.getFeeType();
            BigDecimal feeRatio = zzSchool.getRatio();
            System.out.println(zzStudent.getSchoolId() + "," + zzSchool.getSchoolName() + "referencePrice:" + referencePrice + ",feeType:" + feeType + ",feeRatio:" + feeRatio);
            Assert.notNull(referencePrice, "年参考价不存在");
            Assert.notNull(feeType, "佣金方式不存在");
            Assert.notNull(feeRatio, "佣金、佣金比例方式不存在");
            BigDecimal fee = BigDecimal.ZERO;
            // 1-比例 2-固定金额
            if (1 == feeType) {
                //1个季度 * 续费季度(memberType)
                fee = referencePrice.multiply(feeRatio).divide(new BigDecimal("1200"), 2, RoundingMode.HALF_EVEN).multiply(new BigDecimal(String.valueOf(months)));
            } else if (2 == feeType) {
                fee = feeRatio.divide(new BigDecimal("1200"), 2, RoundingMode.HALF_EVEN).multiply(new BigDecimal(String.valueOf(months)));
            }
            zzStuRenewOrder.setOrderAmount(fee);
            zzStuRenewOrderService.save(zzStuRenewOrder);
        }
    }

    //    @PostConstruct
    public void initExpireAt() {
        List<ZzStudent> zzStudentList = this.list(Wrappers.lambdaQuery(ZzStudent.class)
                .isNull(ZzStudent::getExpireAt));
        if (CollectionUtils.isNotEmpty(zzStudentList)) {
            LocalDateTime now = LocalDateTime.now();
            for (ZzStudent zzStudent : zzStudentList) {
                List<ZzStuRenewOrder> zzStuRenewOrderList = this.zzStuRenewOrderService.list(Wrappers.lambdaQuery(ZzStuRenewOrder.class)
                        .eq(ZzStuRenewOrder::getStuId, zzStudent.getId())
                        .orderByAsc(ZzStuRenewOrder::getId)
                );
                for (ZzStuRenewOrder zzStuRenewOrder : zzStuRenewOrderList) {
                    if (zzStuRenewOrder.getExpireDate().isAfter(now)) {
                        zzStuRenewOrder.setValidFlag(2);
                        zzStudent.setExpireAt(zzStuRenewOrder.getExpireDate());
                        this.updateById(zzStudent);
                        this.zzStuRenewOrderService.updateById(zzStuRenewOrder);
                        break;
                    } else {
                        zzStuRenewOrder.setValidFlag(3);
                        this.zzStuRenewOrderService.updateById(zzStuRenewOrder);
                    }
                }
            }
        }
    }

}